package com.cdream.basic.java8;

import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.RandomUtil;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * @author cdream
 * @date 2021/7/27
 */
public class CompletableFutureExample {
    static ExecutorService executors = Executors.newFixedThreadPool(3, new ThreadFactory() {
        int count = 1;

        @Override
        public Thread newThread(Runnable r) {

            Thread thread = new Thread(r, "custom-executor-" + count++);
            thread.setDaemon(true);
            return thread;
        }
    });
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // CompletableFuture.supplyAsync(() -> {
        //     System.out.println("嘿嘿嘿");
        //     throw new RuntimeException("dog");
        // });
        // ThreadUtil.sleep(1000);
        // System.out.println("dog");
        // CompletableFuture.supplyAsync(() -> 1);
        // System.out.println(1_000_000);

        CompletableFuture<String> cf = CompletableFuture.completedFuture("message");
        System.out.println(cf.isDone());
        System.out.println(cf.getNow("dog"));


        CompletableFuture<Void> cf1 = CompletableFuture.runAsync(() -> {
            System.out.println("守护线程：" + Thread.currentThread().isDaemon());
            System.out.println("子线程" + Thread.currentThread().getName());
            ThreadUtil.sleep(100);
        });
        System.out.println("cf1完成了吗：" + cf1.isDone());
        System.out.println(cf1.join());
        System.out.println("cf1完成了吗：" + cf1.isDone());

        CompletableFuture<String> message = CompletableFuture.completedFuture("message").thenApplyAsync(s -> {
            System.out.println("cf2是守护线程吗：" + Thread.currentThread().isDaemon());
            ThreadUtil.sleep(1000);
            return s.toUpperCase();
        });
        System.out.println("cf2结果：" + message.getNow("dog"));

        CompletableFuture<String> cf3 = CompletableFuture.completedFuture("message").thenApplyAsync(
                s -> {
                    System.out.println("cf3线程名称：" + Thread.currentThread().getName());
                    System.out.println("cf3是守护线程吗：" + Thread.currentThread().isDaemon());
                    ThreadUtil.sleep(100);
                    return s.toUpperCase();
                }, executors
        );
        System.out.println(cf3.getNow("cf3:dog"));

        StringBuilder sb = new StringBuilder();
        CompletableFuture.completedFuture("thenAcceptAsync message").thenApply(sb::append);
        System.out.println(sb.toString());

        StringBuilder sb2 = new StringBuilder();
        CompletableFuture<StringBuilder> cf4 = CompletableFuture.completedFuture("thenAcceptAsync message").thenApplyAsync(sb2::append);
        cf4.join();
        System.out.println("sb2" + sb2.toString());

        CompletableFuture<Void> cf5 = CompletableFuture.runAsync(() -> {
            ThreadUtil.sleep(100);
            System.out.println("1");
        }).thenRunAsync(() -> {
            ThreadUtil.sleep(100);
            System.out.println("2");
        }).thenRunAsync(() -> {
            System.out.println(3);
        });
        cf5.join();

        CompletableFuture<String> cf6 = CompletableFuture.completedFuture("message").thenApplyAsync(s1 -> {
            return s1.toUpperCase();
        });

        CompletableFuture<String> handle = cf6.handle((s, th) -> {
                    System.out.println("s" + s);
                    System.out.println("th" + th.getMessage());
                    return (th != null) ? "message upon cancel" : ";";
                }
        );
        boolean hahahah = cf6.completeExceptionally(new RuntimeException("hahahah"));
        System.out.println(hahahah);
        cf6.isCompletedExceptionally();
        cf6.join();

        CompletableFuture<String> cf7 = CompletableFuture.completedFuture("message").thenApplyAsync(s -> {
            ThreadUtil.sleep(100);
            System.out.println("什么鬼啊");
            return s.toUpperCase();
        });
        // boolean cancel = cf7.cancel(true);
        ThreadUtil.sleep(1500);
        System.out.println("CompleteExceptionally" + cf7.isCompletedExceptionally());
        System.out.println("嘿嘿嘿嘿");

        //
        String original = "Message";
        CompletableFuture<String> cf8 = CompletableFuture.completedFuture(original).thenApplyAsync(s -> {
            ThreadUtil.sleep(100);
            return s.toUpperCase();
        });
        CompletableFuture<String> cf9 = cf8.applyToEither(CompletableFuture.completedFuture("Message").thenApplyAsync(s -> {
            ThreadUtil.sleep(200);
            return s.toLowerCase();
        }), s -> s + "???");
        String join = cf9.join();
        System.out.println("cf9" + join);
        StringBuilder sb3 = new StringBuilder();
        CompletableFuture<Void> cf10 = CompletableFuture.completedFuture(original).thenApplyAsync(s -> {
            ThreadUtil.sleep(130);
            return s.toLowerCase();
        }).acceptEither(CompletableFuture.completedFuture(original).thenApplyAsync(s -> {
            ThreadUtil.sleep(120);
            return s.toUpperCase();
        }), s -> {
            sb3.append(s).append("aaaaaa");
        });
        cf10.join();
        System.out.println(sb3.toString());

        ThreadUtil.sleep(120);

        StringBuilder sb4 = new StringBuilder();
        CompletableFuture<Void> cf11 = CompletableFuture.completedFuture(original).thenApplyAsync(s -> {
            ThreadUtil.sleep(100);
            return s.toUpperCase();
        }).thenAcceptBoth(
                CompletableFuture.completedFuture(original).thenApplyAsync(String::toLowerCase), (s1, s2) -> {
                    sb4.append(s1).append(s2);
                }
        );

        cf11.join();
        System.out.println("sb4" + sb4.toString());


        CompletableFuture<String> cf12 = CompletableFuture.completedFuture(original).thenApplyAsync(s -> s.toUpperCase()).thenCombine(
                CompletableFuture.completedFuture(original).thenApplyAsync(s -> s.toLowerCase()), (s1, s2) -> s1 + s2
        );
        System.out.println("cf12" + cf12.join());

        CompletableFuture<String> cf13 = CompletableFuture.completedFuture(original).thenApply(s -> s.toUpperCase()).thenCombine(
                CompletableFuture.completedFuture(original).thenApply(s -> s.toLowerCase()), (s1, s2) -> s1 + s2
        );

        StringBuilder sb5 = new StringBuilder();
        List<String> messages = Arrays.asList("a", "b", "c");
        List<CompletableFuture<String>> futures = messages.stream().map(msg -> {
            return CompletableFuture.completedFuture(msg).thenApplyAsync(s -> {
                ThreadUtil.sleep(RandomUtil.randomInt(500, 1000));
                return s.toLowerCase();
            });
        }).collect(Collectors.toList());
        CompletableFuture.anyOf(futures.toArray(new CompletableFuture[futures.size()])).whenComplete((res, th) -> {
            System.out.println(res);
        });
        ThreadUtil.sleep(2000);

        StringBuilder sb6 = new StringBuilder();
        List<String> messages2 = Arrays.asList("a", "b", "c");
        List<CompletableFuture<String>> futures2 = messages2.stream().map(msg -> {
            return CompletableFuture.completedFuture(msg).thenApplyAsync(s -> {
                ThreadUtil.sleep(RandomUtil.randomInt(500, 1000));
                return s.toLowerCase();
            });
        }).collect(Collectors.toList());
        CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures2.size()])).whenComplete((res, th) -> {
            System.out.println("allOf" + res);
        });
        ThreadUtil.sleep(2000);
        System.out.println("the end");
    }
}
